<?php/** * Контроллер полей * * Хранит объекты полей, управлет их созданием в БД и их индексами */class FieldsController implements iFieldsController {	private		$typesFields      = array (),		$fields           = array (),
		$assocScalarTypes = array (
			'integer' => 'INT',
			'float' => 'FLOAT',
			'boolean' => 'ENUM(\'0\',\'1\')',
			'header' => 'VARCHAR(255)',
			'text' => 'TEXT',
			'email' => 'VARCHAR(255)',
			'date' => 'INT',
			'birthdate' => 'INT',
			'latin' => 'VARCHAR(255)',
			'image' => 'VARCHAR(255)'
		);		private static $instance = false;		/**	 * Возвращает объект класса FieldsController	 * @return FieldsController	 */	public static function getInstance () {		if (self::$instance === false) {			self::$instance = new FieldsController;		}		return self::$instance;	}		private function __construct () {}		public function __clone () {		throw new CoreException (lang('error_fields_controller_clone',__CLASS__));	}		/**	 * Возвращает информацию о полях типа	 * @param integer $typeId id типа	 * @return array упорядоченный массив с объектами полей	 */	public function getTypeFields ($typeId) {		if (!empty ($this->typesFields[$typeId])) {			return $this->typesFields[$typeId];		}		
		$db = DBController::getInstance ();				$get = $db->query ("SELECT `id` FROM `explay_types_fields` WHERE `type_id` = " . ((int)$typeId) . " ORDER BY `position`");				$this->typesFields[$typeId] = array ();
		$aFileds = array ();
		$aNeedLoadIds = array ();
		$aNeedLoadPos = array ();		
		$n = 0;				while (list ($fieldId) = $db->fetch_row ($get)) {			
			if ($oField = CacheController::load('explay_field_' . $fieldId, CORE_LIFETIME)) {
				$aFileds[$n] = $oField;
				$this->typesFields[$typeId][$oField->getName()] = $oField;
				++$n;
				continue;
			}
			
			$aFileds[$n] = false;
			$aNeedLoadIds[] = $fieldId;
			$aNeedLoadPos[$fieldId] = $n;
			
			++$n;		}
		
		if (!count ($aNeedLoadIds)) {			return $this->typesFields[$typeId];
		}
		
		$get = $db->query ("SELECT SQL_CACHE * FROM `explay_types_fields` WHERE `id` IN ('" . implode("','", $aNeedLoadIds) . "')");
		
		while ($values = $db->fetch_array ($get)) {
			$oField = new Field ($values);
			
			CacheController::save('explay_field_' . $values['id'], $oField, CORE_LIFETIME);
			
			$pos = $aNeedLoadPos[$values['id']];
			$aFileds[$pos] = $oField;
		}
		
		foreach ($aFileds as $oField) {
			$this->fields[$oField->getId()] = $oField;
			$this->typesFields[$typeId][$oField->getName()] = $oField;
		}
		
		return $this->typesFields[$typeId];	}			/**	 * Возвращает информацию о поле по его id	 * @param integer $fieldId id поля	 * @return Field	 */	public function getField ($fieldId) {		if (isset ($this->fields[$fieldId])) {			return $this->fields[$fieldId];		}				if ($oField = CacheController::load('explay_field_' . $fieldId, CORE_LIFETIME)) {
			return $this->fields[$fieldId] = $oField;
		}				$db = DBController::getInstance ();		$get = $db->query ("SELECT SQL_CACHE * FROM `explay_types_fields` WHERE `id` = " . (int) $fieldId);				if ($db->num_rows ($get) == 0) {			return $this->fields[$fieldId] = false;		}				$oField = new Field ($db->fetch_array ($get));				CacheController::save('explay_field_' . $fieldId, $oField, CORE_LIFETIME);				return $this->fields[$fieldId] = $oField;	}
	
	/**
	 * Получить информацию о поле
	 * @param integer $fieldId
	 * @return array
	 */
	public function getFieldSqlInfo ($fieldId) {
		if (!$oField = $this->getField ($fieldId)) {
			return false;
		}
		
		$res = array ();
		$oType = TypesController::getInstance()->getTypeById ($oField->getTypeId ());
		
		$db = DBController::getInstance ();
		
		$get = $db->query ('DESCRIBE `' . $oType->getTableName() . '` `' . $oField->getName() . '`');
		
		list (,,$null,,$default) = mysql_fetch_row ($get);
		
		$res['default'] = $default;
		
		return $res;
	}	/**	 * Создает новое поле	 * @param Object $oField объект с свойствами поля	 * @return boolean	 */	public function createField (Object $oField, $defaultValue) {		$character = $oField->getValue ('character');
		
		$aOtherTypes = array ('guide','multiguide','tags','object_value');
		if (in_array ($character, $aOtherTypes)) {
			return true;
		}
		
		if (!isset ($this->assocScalarTypes[$character])) {
			return false;
		}
		
		$type = $this->assocScalarTypes[$character];		
		$valueState = $oField->getValue ('required') ? 'NOT NULL' : 'NULL';
		
		if (!$oField->getValue ('required')) {
			$valueState .= $defaultValue == 'NULL' ? ' DEFAULT NULL' : ' DEFAULT \'' . $defaultValue . '\'';
		}

		$oType = TypesController::getInstance()->getTypeById ($oField->getValue ('type_id'));
		
		$sSQL = "ALTER TABLE `" . $oType->getTableName() ."` ADD `" . $oField->getValue('field_name') . "` " . $type . " " . $valueState;
		
		DBController::getInstance()->query($sSQL);
		
		return true;
	}
	
	public function changeField ($oldName, Object $oField, $defaultValue) {
		$character = $oField->getValue ('character');
		
		$aOtherTypes = array ('guide','multiguide','tags','object_value');
		if (in_array ($character, $aOtherTypes)) {
			return true;
		}
		
		if (!isset ($this->assocScalarTypes[$character])) {
			return false;
		}
		
		$type = $this->assocScalarTypes[$character];		
		$valueState = $oField->getValue ('required') ? 'NOT NULL' : 'NULL';
		
		if (!$oField->getValue ('required')) {
			$valueState .= $defaultValue == 'NULL' ? ' DEFAULT NULL' : ' DEFAULT \'' . $defaultValue . '\'';
		}
		
		$oType = TypesController::getInstance()->getTypeById ($oField->getValue ('type_id'));
		
		$sSQL = "ALTER TABLE `" . $oType->getTableName() ."` CHANGE `" . $oldName . "` `" . $oField->getValue('field_name') . "` " . $type . " " . $valueState;

		DBController::getInstance()->query($sSQL);
		
		return true;
	}		/**	 * Удаляет поле	 * @param Field $oField	 * @return boolean	 */	public function deleteField (Object $oField) {		$aOtherTypes = array ('guide','multiguide','tags','object_value');
		if (in_array ($oField->getValue ('character'), $aOtherTypes)) {
			return true;
		}
		
		$oType = TypesController::getInstance()->getTypeById ($oField->getValue ('type_id'));
		
		DBController::getInstance()->query("ALTER TABLE `" . $oType->getTableName() . "` DROP `" . $oField->getValue('field_name') . "`");
		
		return true;	}	}